package com.alibaba.chaosblade.box.toolsmgr.ansible.command;

import com.alibaba.chaosblade.box.toolsmgr.ansible.AnsibleCommand;
import com.alibaba.chaosblade.box.toolsmgr.ansible.AnsibleCommandExtraVarsUtil;
import com.alibaba.chaosblade.box.toolsmgr.ansible.AnsibleConstants;
import com.alibaba.chaosblade.box.toolsmgr.model.MgrRequest;
import com.google.common.base.Joiner;

import java.util.List;

/**
 * @author: xinyuan.ymm
 * @create: 2022-01-07 9:41 PM
 */
public class AnsibleShellScriptCommand implements AnsibleCommand, AnsibleConstants {

    /**
     * 构建Ansible Shell脚本执行命令
     * <p>
     * 根据管理请求参数构建完整的Ansible命令行，包括目标主机、用户、执行命令和额外变量等信息
     *
     * @param mgrRequest 管理请求参数，包含目标主机IP、用户、端口、密码和要执行的命令等信息
     * @return 返回构建完成的Ansible命令行字符串
     */
    @Override
    public String getCommand(MgrRequest mgrRequest) {
        // 构建基础ansible命令，指定目标主机IP
        String sb = String.format("ansible %s", mgrRequest.getInstanceIp());
        
        // 如果指定了用户，则添加用户参数
        if (!mgrRequest.getInstanceUser().isEmpty()) {
            sb = String.format("%s -u %s", sb, mgrRequest.getInstanceUser());
        }
        
        // 添加shell模块和执行的命令
        sb = String.format("%s -m shell -a 'sh -c  \"%s\"'", sb, mgrRequest.getCommand());

        // 添加额外变量（如端口、密码等）
        return String.format("%s %s", sb, AnsibleCommandExtraVarsUtil.getExtraVars(mgrRequest));
    }
    
    /**
     * 判断Ansible命令执行结果是否成功
     * <p>
     * 根据Ansible执行结果列表判断命令是否执行成功，通过检查结果中是否包含成功或失败的关键字
     *
     * @param result Ansible命令执行结果列表，每行结果作为一个元素
     * @param ignoreBackgroundTimeout 是否忽略后台超时情况
     * @return 返回true表示执行成功，false表示执行失败
     */
    @Override
    public boolean resultPredicate(List<String> result, boolean ignoreBackgroundTimeout) {
        // 检查结果是否为空
        if (result != null && result.size() > 0) {
            // 将结果列表合并为一个字符串
            String resultContent = Joiner.on(" ").join(result);
            
            // 如果忽略后台超时并且结果包含超时信息，则返回true
            if(ignoreBackgroundTimeout && resultContent.contains("timed out waiting for module completion")){
                return true;
            }

            // 如果结果包含FAILED关键字，则返回false表示执行失败
            if (resultContent.contains("FAILED")) {
                return false;
            }
            
            // 如果结果包含成功标识（rc=0, SUCCESS, CHANGED），则返回true表示执行成功
            if (resultContent.contains("rc=0")
                || resultContent.contains("SUCCESS")
                || resultContent.contains("CHANGED")) {
                return true;
            }
        }
        // 默认返回false表示执行失败
        return false;
    }
}
